﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MySql.Data.MySqlClient;
using DateBaseConnectionPool;

namespace TestMySqlConnetPoll
{
    /// <summary>
    /// 模拟量表操作说明：
    /// 模拟量表的主要功能：
    /// 1.读取日曲线
    ///   日曲线只能单路模拟量读取
    ///   日曲线换设备类型后清除日曲线表，换日期后清除日曲线表
    ///   日曲线缓冲区保存一种设备类型的所有设备的值列表
    ///   日曲线的时间列表为静态值，显示界面直接从当前天反推30天做日期列表
    /// 1.1 日曲线对外变量 DailyCurveValueList 存储日曲线数据，以设备名称做键值，包含该设备的所有属性的日曲线值列表
    /// 1.2 日曲线对外变量 Ready_DailyCurveValueList,从数据库中取某种模拟量时，读取成功标准。
    /// 1.3 日曲线对外变量 ErrorFlag ，模拟量表操作出错变量，检测到该变量不为0，则读取数据库失败
    /// 1.3 日曲线操作流程
    /// 1.3.1 调用CheckInDailyValueList，检查模拟量数据是否在缓冲区，返回true则直接到缓冲区取数据；
    /// 1.3.2 调用ReadDailyValueList读取数据库内的数据，该函数启动一个查询数据库线程后立即返回，调用该函数后，检查Ready_DailyCurveValueList和ErrorFlag获得读取数据库结果
    /// </summary>
    [Serializable]
    public class DevClass   //设备的结构        
    {
        public string AttriName = "";   //设备的属性
        public objSingleAnalogStruct objSet = new objSingleAnalogStruct();
        public List<objTimeValue> ValueList = new List<objTimeValue>();   //属性的值列表
    }
    [Serializable]   
    public class ReplayClass
    {
        public int AnalogNo = -1;
        public objSingleAnalogStruct objSet = new objSingleAnalogStruct();
        public List<objTimeValue> ValueList = new List<objTimeValue>();   //属性的值列表
    }
    public class AnalogTable
    {

        #region  外部函数接口，模拟量日曲线，回放曲线   外部变量定义
        /// <summary>
        /// 日曲线以设备号做键值,回放以设备类型做键值
        /// </summary>        
        private string DailyCsmDevTypeName = "";                   //日曲线的设备类型名称
        private int DailyCurveDay = 0;                             //日曲线的某一天，换天后，清除内存数据
        
        /// <summary>
        /// 站机读取数据的缓冲区。
        /// </summary>
        public Dictionary<string, List<DevClass>> DailyCurveValueList = new Dictionary<string, List<DevClass>>(); //以设备名称做键值
        /// <summary>
        /// 站机响应终端读取日曲线命令时读到数据的缓冲区，用于终端调阅日曲线时使用
        /// </summary>
        public Dictionary<objCodeDev, List<objTimeValue>> TermianlValueList = new Dictionary<objCodeDev, List<objTimeValue>>();
        /// <summary>
        /// //回放时读取模拟量的缓冲区,以模拟量类型做缓冲区
        /// </summary>
        public Dictionary<AnalogCodeType, List<ReplayClass>> ReplayValueList = new Dictionary<AnalogCodeType, List<ReplayClass>>(); 
        //public bool Ready_DailyCurveTimeList = false;       //模拟量日曲线时间列表准备好标志
        public bool Ready_DailyCurveValueList = false;        //模拟量日曲线值列表准备好标志
        public bool Ready_ReplayValueList = false;            //回放数据准备好标志 ,所有模拟量表读完成时，该标准为13，表示回放数据准备完成
        public int ErrorFlag = 0;
        private int ReadReplayAnalogTypeNum = 0;              //读回放数据时，完成读模拟量类型的个数
        private Mutex readMutex = new Mutex();
        /// <summary>
        /// 读取模拟量日曲线时间列表
        /// </summary>
        /// <param name="Type"></param>
        //public void Read_DailyCurveTimeList(AnalogCodeType AnaType)
        //{
        //    Ready_DailyCurveTimeList = false;
        //    ThreadStruct obj = new ThreadStruct();
        //    obj.TableName = GetTableName(AnaType);
        //    obj.AnalogType = AnaType;
        //    ThreadPool.QueueUserWorkItem(new WaitCallback(Thread_ReadAnalogTableTimeList), obj);
        //}

        struct ThreadStruct
        {
            public string TableName;
            public CSM_DevType DevType;
            public AnalogCodeType AnalogType;
            public string CsmName;
            public string DevName;
            public string AttriName;
            public int p_day;
            public int dev_no;
            public int s_time;
            public int e_time;
            public int AnalogTypeNum;
        }

        private Mutex keyMutex = new Mutex();
        private static int keykey = 0;
        

        /// <summary>
        /// 初始化valuelist 主要是取报警上限和下限
        /// </summary>
        /// <param name="CsmTypeName"></param>
        /// <param name="DevName"></param>
        /// <param name="AttriName"></param>
        private void InitDailyValueList(string CsmTypeName, string DevName, string AttriName)
        {
            DevClass objDev = new DevClass();
            objDev.AttriName = AttriName;
            objDev.objSet = c_Device.GetSingleAnalogConfig(CsmTypeName, DevName, AttriName);
            objDev.ValueList.Clear();
            if (DailyCurveValueList.ContainsKey(DevName))
            {
                DailyCurveValueList[DevName].Add(objDev);
            }
            else
            {
                List<DevClass> k = new List<DevClass>();
                k.Add(objDev);
                DailyCurveValueList.Add(DevName, k);
            }
        }
        /// <summary>
        /// 检查模拟量是否在缓冲区内
        /// </summary>
        /// <param name="CsmTypeName"></param> 设备类型名称
        /// <param name="DevName"></param>设备名称
        /// <param name="AttriName"></param>属性名称
        /// <param name="p_day"></param>天
        /// <returns></returns>
        public bool CheckInDailyValueList(string CsmTypeName, string DevName, string AttriName, int p_day)
        {
            if (p_day == DailyCurveDay && CsmTypeName == DailyCsmDevTypeName)
            {
                if (DailyCurveValueList.ContainsKey(DevName))    //查找是否在缓冲区内
                {
                    int len = DailyCurveValueList[DevName].Count;
                    for (int i = 0; i < len; i++)
                    {
                        string s = DailyCurveValueList[DevName][i].AttriName;
                        if (AttriName == s)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }        
        /// <summary>
        /// 外部函数，读取模拟量数据,给站机使用
        /// </summary>
        /// <param name="CsmTypeName"></param>  模拟量名称
        /// <param name="DevName"></param>设备名称
        /// <param name="AttriName"></param>属性名称
        /// <param name="p_day"></param>日期
        public void ReadDailyValueList(string CsmTypeName, string DevName, string AttriName, DateTime p_day)
        {
            Ready_DailyCurveValueList = false;
            ErrorFlag = 0;
            if (CsmTypeName != DailyCsmDevTypeName)
            {
                DailyCurveValueList.Clear();
                DailyCsmDevTypeName = CsmTypeName;
            }
            if (p_day.Day != DailyCurveDay)
            {
                DailyCurveValueList.Clear();
                DailyCurveDay = p_day.Day;
            }
            if (CheckInDailyValueList(CsmTypeName, DevName, AttriName,p_day.Day))
            {
                Ready_DailyCurveValueList = true;
                return;
            }
            ThreadStruct obj = new ThreadStruct();
            if(c_Device.MsgDataBaseTable.ContainsKey(CsmTypeName))
            {
                obj.TableName = c_Device.MsgDataBaseTable[CsmTypeName];
            }
            else
            {
                ErrorFlag = 1;
                return;
            }
            AnalogObj o = c_Device.GetAnalogDevNo(CsmTypeName,DevName,AttriName);
            if(o.type == AnalogCodeType.None || o.devNo == -1)
            {
                ErrorFlag = 1;
                return;
            }
            //InitDailyValueList(CsmTypeName, DevName, AttriName);
            obj.AnalogType = o.type;
            obj.dev_no = o.devNo;
            obj.p_day = p_day.Day;
            obj.s_time = MySql.DateTimeToTime_t(new DateTime(p_day.Year, p_day.Month, p_day.Day, 0, 0, 0));
            obj.e_time = MySql.DateTimeToTime_t(new DateTime(p_day.Year, p_day.Month, p_day.Day, 23, 59, 59));
            obj.CsmName = CsmTypeName;
            obj.DevName = DevName;
            obj.AttriName = AttriName;
            ThreadPool.QueueUserWorkItem(new WaitCallback(Thread_ReadDailyValueList), obj);
        }
        /// <summary>
        /// 外部函数，读取模拟量数据，给终端使用.
        /// </summary>
        /// <param name="AnalogType"></param>
        /// <param name="DevNo"></param>
        /// <param name="p_day"></param>
        public void ReadDailyValueList(byte AnalogType, int DevNo, DateTime p_day)
        {
            TermianlValueList.Clear();
            ErrorFlag = 0;
            Ready_DailyCurveValueList = false;
            ThreadStruct obj = new ThreadStruct();            
            obj.TableName = c_Device.GetTableName((AnalogCodeType)AnalogType);
            obj.AnalogType = (AnalogCodeType)AnalogType;
            obj.dev_no = DevNo;
            obj.p_day = p_day.Day;
            obj.s_time = MySql.DateTimeToTime_t(new DateTime(p_day.Year, p_day.Month, p_day.Day, 0, 0, 0));
            obj.e_time = MySql.DateTimeToTime_t(new DateTime(p_day.Year, p_day.Month, p_day.Day, 23, 59, 59));
            obj.CsmName = "终端";
            obj.DevName = "终端";
            obj.AttriName = "终端";
            ThreadPool.QueueUserWorkItem(new WaitCallback(Thread_ReadDailyValueList), obj);
        }

        /// <summary>
        /// 读取模拟量回放值，每种模拟量表都需要读取
        /// </summary>
        /// <param name="s_time"></param>
        /// <param name="e_time"></param>
        public void ReadReplayValue(int s_time, int e_time)
        {
            Ready_ReplayValueList = false;
            ReadReplayAnalogTypeNum = 0;
            ReplayValueList.Clear();
            ThreadStruct obj = new ThreadStruct();
            obj.s_time = s_time;
            obj.e_time = e_time;
            int validNum = 0;
            int AnalogTypeNum = c_Device.AnalogcCollocation.Count;
            for (int i = 0; i < AnalogTypeNum;i++ )
            {
                AnalogCodeType type = c_Device.AnalogcCollocation[i].type;
                if (type == AnalogCodeType.半自动闭塞电压和电流 || type == AnalogCodeType.电缆绝缘 || type == AnalogCodeType.电源漏流)
                { }
                else
                {
                    string TableName = c_Device.GetTableName(type);
                    obj.TableName = TableName;
                    obj.AnalogType = type;
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadAnalogTableReplayValue), obj);
                    validNum++;
                }
            }
            obj.AnalogTypeNum = validNum;
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadCheckReplayReady), obj);
        }
        /// <summary>
        /// 指定取几种模拟量的回放数据
        /// </summary>
        /// <param name="s_time"></param>
        /// <param name="e_time"></param>
        /// <param name="AnalogSet"></param>
        public void ReadReplayValue(int s_time, int e_time, List<byte> AnalogSet)
        {
            Ready_ReplayValueList = false;
            ReadReplayAnalogTypeNum = 0;
            ReplayValueList.Clear();
            ThreadStruct obj = new ThreadStruct();
            obj.s_time = s_time;
            obj.e_time = e_time;
            //int AnalogTypeNum = c_Device.AnalogcCollocation.Count;
            for (int i = 0; i < AnalogSet.Count; i++)
            {
                AnalogCodeType type = (AnalogCodeType)AnalogSet[i];
                string TableName = c_Device.GetTableName(type);
                obj.TableName = TableName;
                obj.AnalogType = type;
                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadAnalogTableReplayValue), obj);
            }
            obj.AnalogTypeNum = AnalogSet.Count;
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadCheckReplayReady), obj);
        }

        private void ThreadCheckReplayReady(object o)
        {
            ThreadStruct obj = (ThreadStruct)o;
            int AnalogTypeNum = obj.AnalogTypeNum;
            DateTime dtime = DateTime.Now;
            while (true)
            {
                if (ErrorFlag != 0) break;
                if (ReadReplayAnalogTypeNum == AnalogTypeNum)
                {
                    Ready_ReplayValueList = true;
                    break;
                }
                Thread.Sleep(500);
                if(DateTime.Now.Subtract(dtime).TotalSeconds>=1200)
                {
                    ErrorFlag = 9;
                    break;
                }
            }
        }

        #region  模拟量表操作 
 
        /// <summary>
        /// 模拟量表插入数据，适用于dyp,ups,wdw,zngddl,qjgddl,mcgddl,dcbsdy,xhj,dmh,zhanlian,qjjc 表格,type = 0xff时，表示表格中无类型区分.
        /// jz$fz$bzb 表需要带设备类型,其它表可以不带类型
        /// </summary>
        private bool Insert_AnalogData(string TableName, byte p_day, Int32 u_Time, Int16 Dev_no, Int32[] value, AnalogCodeType codetype)
        {
            if (TableName == "") return false;
            bool InsertFlag = false;
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    InsertFlag = false;
                }
                        
                            

                if (con != null)
                {
                    StringBuilder InsertStatement = new StringBuilder();

                    InsertStatement.Append(string.Format("insert into {0}(p_day,u_time,codetype,Dev_no", TableName));

                    for (int i = 0; i < 20; i++)
                    {
                        InsertStatement.Append(string.Format(",value{0}", i + 1));
                    }
                    InsertStatement.Append(")values(?p_day,?u_time");

                    InsertStatement.Append(",?codetype,?Dev_no");
                    for (int i = 0; i < 20; i++)
                    {
                        InsertStatement.Append(string.Format(",?value{0}", i + 1));
                    }
                    InsertStatement.Append(")");
                    MySqlCommand InsertCommand = new MySqlCommand(InsertStatement.ToString(), con);

                    InsertCommand.Parameters.Add(new MySqlParameter("?p_day", MySqlDbType.Byte)).Value = p_day;
                    InsertCommand.Parameters.Add(new MySqlParameter("?u_time", MySqlDbType.Int32)).Value = u_Time;
                    InsertCommand.Parameters.Add(new MySqlParameter("?codetype", MySqlDbType.Byte)).Value = (byte)codetype;
                    InsertCommand.Parameters.Add(new MySqlParameter("?Dev_no", MySqlDbType.Int16)).Value = Dev_no;

                    string TmpValueS = "";
                    for (int i = 0; i < 20; i++)
                    {
                        TmpValueS = string.Format("?value{0}", i + 1);
                        InsertCommand.Parameters.Add(new MySqlParameter(TmpValueS, MySqlDbType.Int32)).Value = value[i];
                    }
                    try
                    {
                        int k = InsertCommand.ExecuteNonQuery();
                        if (k == 1) InsertFlag = true;        //写入成功
                        else InsertFlag = false;              //写入失败
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                        InsertFlag = false;       //写入失败
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                    }
                }
            }
            return InsertFlag;
        }
        /// <summary>
        /// 填充日报表数据，确保每秒都有点
        /// </summary>
        /// <param name="DevName"></param>
        /// <param name="AttriName"></param>
        private void FillAnalogDailyCurveData(string DevName, string AttriName)
        {
            if (DailyCurveValueList.ContainsKey(DevName))
            {
                for (int i = 0; i < DailyCurveValueList[DevName].Count; i++)
                {
                    if (DailyCurveValueList[DevName][i].AttriName == AttriName)
                    {
                        List<objTimeValue> li = DailyCurveValueList[DevName][i].ValueList;
                        List<objTimeValue> t1 = new List<objTimeValue>();
                        objTimeValue fobj = new objTimeValue();     //最开始的一个点                        
                        for (int x = 0; x < li.Count; x++)
                        {
                            if (x == 0)
                            {
                                fobj = li[x];   //第一个点
                                t1.Add(fobj);
                            }
                            else
                            {
                                objTimeValue nobj = new objTimeValue();
                                nobj = li[x];  //第2个点
                                int n = nobj.u_time - fobj.u_time;
                                if (n >= 10)    //超过10秒无数据，认为是断开,填-1值
                                {
                                    fobj.Dvalue = -1;
                                    fobj.Tvalue.DecimalNum = 0;
                                    fobj.Tvalue.Value = -1;
                                    fobj.Tvalue.ValueType = "";
                                }
                                for (int y = 0; y < n - 1; y++) //要补点的数目
                                {
                                    fobj.u_time++;
                                    t1.Add(fobj);
                                }
                                t1.Add(nobj);
                                fobj = nobj;
                            }
                        }
                        DailyCurveValueList[DevName][i].ValueList = t1;     //从新赋值到缓冲区中.
                        break;
                    }
                }
            }     
        }

        /// <summary>
        /// 读取模拟量日曲线
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="p_day"></param>
        /// <param name="Dev_no"></param>
        /// <param name="devtype"></param>
        /// <param name="codetype"></param>
        /// <returns></returns>
        private void Thread_ReadDailyValueList(object o)
        {
            ThreadStruct obj = new ThreadStruct();
            obj = (ThreadStruct)o;
            string TableName = obj.TableName;
            byte p_day = (byte)obj.p_day;
            Int16 Dev_no = (Int16)obj.dev_no;
            AnalogCodeType codetype = obj.AnalogType;
            string CsmDevName = obj.CsmName;
            string DevName = obj.DevName;
            string AttriName = obj.AttriName;

            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    ErrorFlag = 2;
                }
                        
                if (con != null)
                {
                    StringBuilder SelectStatement = new StringBuilder();

                    SelectStatement.Append("select u_time");

                    for (int i = 1; i < 21; i++)
                    {
                        SelectStatement.Append(string.Format(",value{0}", i));
                    }
                    SelectStatement.Append(string.Format(" from {0} ", TableName));
                    SelectStatement.Append(string.Format("where p_day = {0} and dev_no = {1} and codetype = {2}", p_day, Dev_no, (byte)codetype));
                    SelectStatement.Append(string.Format(" and u_time >= {0} and u_time <= {1}", obj.s_time, obj.e_time));

                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时
                        MySqlDataReader read = selectCommand.ExecuteReader();
                        DevClass tmpObj = new DevClass();
                        tmpObj.AttriName = AttriName;
                        tmpObj.objSet = c_Device.GetSingleAnalogConfig(CsmDevName, DevName, AttriName);
                        ///------终端变量
                        objCodeDev devObj = new objCodeDev();
                        devObj.codetype = (byte)codetype;
                        devObj.dev_no = Dev_no;
                        List<objTimeValue> teList = new List<objTimeValue>();
                        ///-------
                        while (read.Read())
                        {
                            int u_time = read.GetInt32(read.GetOrdinal("u_time"));
                            for (int i = 1; i < 21; i++)
                            {
                                string s = "value" + i.ToString();
                                Int32 TmpValue = read.GetInt32(read.GetOrdinal(s));
                                objTimeValue k = new objTimeValue();
                                k.u_time = u_time + ((TmpValue >> 16) & 0xffff);
                                Int16 value = (Int16)(TmpValue & 0xffff);
                                string tmp = c_Device.GetAnalogTypeName(codetype);
                                ObjValue kkk = c_RealTimeValue.ConvertAnalogValue(tmp, value);
                                k.Dvalue = value;
                                k.Tvalue = kkk;
                                if (AttriName != "终端")
                                {
                                    tmpObj.ValueList.Add(k);
                                }
                                else
                                {
                                    teList.Add(k);
                                }
                            }
                        }
                        read.Close();
                        if (AttriName != "终端")
                        {
                            if (DailyCurveValueList.ContainsKey(DevName))
                            {
                                DailyCurveValueList[DevName].Add(tmpObj);
                            }
                            else
                            {
                                List<DevClass> m = new List<DevClass>();
                                m.Add(tmpObj);
                                DailyCurveValueList.Add(DevName, m);
                            }
                            //FillAnalogDailyCurveData(DevName, AttriName); //填充每秒数据
                        }
                        else TermianlValueList.Add(devObj,teList);  //放入终端缓冲区，终端的在发送时填充
                       
                        Ready_DailyCurveValueList = true;
                    }
                    catch (MySqlException e)
                    {
                        ErrorFlag = 3;
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        ErrorFlag = 4;
                    }
                }
                else ErrorFlag = 6;
            }
            else ErrorFlag = 7;
        }
        #region 废弃，读取模拟量时间列表
        ///// <summary>
        ///// 加入到日曲线的时间列表
        ///// </summary>
        ///// <param name="type"></param>
        ///// <param name="p_day"></param>
        //private void Add_DailyTimeList(byte p_day)
        //{            
        //    objDate t = new objDate();
        //    t.year = DateTime.Now.Year;
        //    t.month = (byte)DateTime.Now.Month;
        //    t.day = p_day;

        //    if (p_day <= DateTime.Now.Day) //当前月
        //    {
        //        if (DailyCurveTimeList.Contains(t)) { }
        //        else DailyCurveTimeList.Add(t);
        //    }
        //    else //上月数据
        //    {
        //        if (DateTime.Now.Month != 1)  //不是一月，不需要跨年
        //        {
        //            t.month = t.month--;
        //            if (DailyCurveTimeList.Contains(t)) { }
        //            else DailyCurveTimeList.Add(t);
        //        }
        //        else
        //        {
        //            t.year--;
        //            t.month--;
        //            if (DailyCurveTimeList.Contains(t)) { }
        //            else DailyCurveTimeList.Add(t);
        //        }
        //    }
        //}

        ///// <summary>
        ///// 读取模拟量日曲线的 时间列表，
        ///// </summary>
        ///// <param name="o"></param>
        ///// <returns></returns>
        //private void Thread_ReadAnalogTableTimeList(object o)
        //{
        //    ThreadStruct TreadStruct = new ThreadStruct();
        //    TreadStruct = (ThreadStruct)o;
        //    string TableName = TreadStruct.TableName;              
        //    DailyCurveTimeList.Clear();
        //    DailyCurveValueList.Clear();
        //    if (MySql.c != null && MySql.c.State == PoolState.Run)
        //    {
        //        MySqlConnection con = new MySqlConnection();
        //        string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString()+ (MySql.key++).ToString();
        //        try
        //        {
        //            con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
        //        }
        //        catch (MySqlException ex)
        //        {
        //            //写异常日志
        //        }
        //        if (con != null)
        //        {
        //            StringBuilder SelectStatement = new StringBuilder();

        //            SelectStatement.Append(string.Format("select(p_day) from {0}where p_day >=1 and p_day <=31", TableName));

        //            try
        //            {
        //                MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
        //                selectCommand.CommandTimeout = 120;   //120s操作超时
        //                MySqlDataReader read = selectCommand.ExecuteReader();
        //                while (read.Read())
        //                {
        //                    byte day = read.GetByte(read.GetOrdinal("p_day"));
        //                    Add_DailyTimeList(day);
        //                }
        //                Ready_DailyCurveTimeList = true;       //时间列表准备好标志
        //                read.Close();
        //            }
        //            catch (MySqlException e)
        //            {
        //                //写错误日志
        //            }
        //        }
        //        try
        //        {
        //            MySql.c.DisposeConnection(key);
        //        }
        //        catch (MySqlException e)
        //        {
        //            //写错误日志
        //        }
        //    }
        //    return;
        //}
        #endregion
        /// <summary>
        /// 加入到回放缓冲区，？两list是否可以直接赋值.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="u_time"></param>
        /// <param name="dev_no"></param>
        /// <param name="value"></param>
        private void AddToReplayValueList(AnalogCodeType type, Int16 Analog_no, List<objTimeValue> value)
        {
            //DevClass obj = new DevClass();
            //string AnalogTypeName = c_Device.GetAnalogTypeName(type);   //模拟量类型名

            //#region 找模拟量的报警值
            //int len = c_Device.AnalogcCollocation.Count;
            //objConfigAnalog objc = new objConfigAnalog();
            //for (int i = 0; i < len; i++)
            //{
            //   string s = c_Device.AnalogcCollocation[i].TypeName;
            //   if (s == AnalogTypeName)
            //   {
            //       objc.type = c_Device.AnalogcCollocation[i].type;
            //       objc.TypeName = c_Device.AnalogcCollocation[i].TypeName;
            //       objc.IniFileName = c_Device.AnalogcCollocation[i].IniFileName;
            //       break;
            //   }
            //}            
            //#endregion
            ReplayClass objReplay = new ReplayClass();
            objReplay.AnalogNo = Analog_no;
            objReplay.objSet = c_Device.GetSingleAnalogConfig_Inf(type,Analog_no);
            for (int k = 0; k < value.Count; k++)
            {
                objReplay.ValueList.Add(value[k]);
            }
            if (Monitor.TryEnter(ReplayValueList, 500))
            {
                if (ReplayValueList.Keys.Contains(type))
                {
                    int l = ReplayValueList[type].Count;
                    for (int i = 0; i < l; i++)
                    {
                        if (ReplayValueList[type][i].AnalogNo == Analog_no)  //找到了设备,原来有这个模拟量在，直接加入值
                        {
                            for (int k = 0; k < value.Count; k++)
                            {
                                ReplayValueList[type][i].ValueList.Add(value[k]);
                            }
                            Monitor.Exit(ReplayValueList);
                            return;
                        }
                    }
                    //一个新的模拟量序号，需要加入报警上限，报警下限
                    ReplayValueList[type].Add(objReplay);
                    Monitor.Exit(ReplayValueList);
                    return;
                }
                else //一种新的模拟量类型
                {
                    List<ReplayClass> k = new List<ReplayClass>();
                    k.Add(objReplay);
                    ReplayValueList.Add(type, k);
                }
                Monitor.Exit(ReplayValueList);
            }
            else
            {
                ErrorFlag = 11;
            }
        }

        /// <summary>
        /// 取某一段时刻所有的模拟量
        /// 需考虑跨天查询
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="s_time"></param>
        /// <param name="e_time"></param>
        /// <param name="type"></param> 设备类型有效，取某一段时间某一种设备类型的值，否则取所有类型的值
        /// <returns></returns>
        private void ThreadReadAnalogTableReplayValue(object o)
        {
            ThreadStruct obj = new ThreadStruct();
            obj = (ThreadStruct)o;
            string TableName = obj.TableName;
            Int32 s_time = obj.s_time;
            Int32 e_time = obj.e_time;
            AnalogCodeType type = obj.AnalogType;
                        
            if (TableName == "") return;
            bool OneDay = true;         //开始时间和结束时间是否在同一天内
            int p_day = 0;             //第一天的天
            int sencond_day = 0;       //第二天的天

            DateTime st = MySql.Time_tToDateTime(s_time);
            DateTime et = MySql.Time_tToDateTime(e_time);

            if (st.Day == et.Day)
            {
                OneDay = true;
                p_day = st.Day;
            }
            else
            {
                OneDay = false;
                p_day = st.Day;
                sencond_day = et.Day;
            }

            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    ErrorFlag = 1;
                }
                        
                if (con != null)
                {
                    StringBuilder SelectStatement = new StringBuilder();
                    SelectStatement.Append("select u_time,dev_no");

                    for (int i = 0; i < 20; i++)
                    {
                        SelectStatement.Append(string.Format(",value{0}", i + 1));
                    }
                    SelectStatement.Append(string.Format(" from {0} ", TableName));
                    if (OneDay) SelectStatement.Append(string.Format("where p_day = {0} ", p_day));
                    else SelectStatement.Append(string.Format("where (p_day = {0} or p_day = {1}) ",p_day ,sencond_day));
                    
                    SelectStatement.Append(string.Format("and u_time >={0} and u_time<={1} and codetype = {2} order by u_time", s_time, e_time, (int)type));

                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();                        
                        while (read.Read())
                        {
                            objAnalogDev objDev = new objAnalogDev();
                            int u_time = read.GetInt32(read.GetOrdinal("u_time"));
                            Int16 dev_no = read.GetInt16(read.GetOrdinal("dev_no"));
                            objDev.dev_no = dev_no;
                            for (int i = 1; i < 21; i++)
                            {
                                string s = "value" + i.ToString();
                                Int32 TmpValue = read.GetInt32(read.GetOrdinal(s));
                                objTimeValue k = new objTimeValue();
                                k.u_time = u_time + ((TmpValue >> 16) & 0xffff);
                                Int16 value = (Int16)(TmpValue & 0xffff);
                                string abc = c_Device.GetAnalogTypeName(type);
                                ObjValue kkk = c_RealTimeValue.ConvertAnalogValue(abc, value);
                                k.Dvalue = value;
                                k.Tvalue = kkk;
                                
                                objDev.dValue.Add(k);
                            }
                            AddToReplayValueList(type, dev_no, objDev.dValue);
                        }
                        read.Close();
                        Interlocked.Increment(ref ReadReplayAnalogTypeNum);
                    }
                    catch (MySqlException e)
                    {
                        ErrorFlag = 2;
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        ErrorFlag = 3;
                    }
                }
                else ErrorFlag = 6;
            }
            else ErrorFlag = 7;
        }
        #endregion
        #endregion
    }
}
